/* Copyright (c) 2015,2016 Lucky Byte, Inc.
 */
package com.lucky_byte.pay.jar.lualib;

import java.util.List;

import org.luaj.vm2.LuaUserdata;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.OneArgFunction;
import org.luaj.vm2.lib.TwoArgFunction;
import org.luaj.vm2.lib.ZeroArgFunction;

import com.google.gson.JsonObject;
import com.lucky_byte.pay.jar.Packet;

/**
 * 报文，一个 Lua Table
 */
public class LuaPacket extends ZeroArgFunction
{
	private Packet  packet;
	private LuaValue library;

	public LuaPacket(Packet packet) {
		if (packet == null) {
			throw new RuntimeException("参数 packet 不能为空.");
		}
		this.packet = packet;
	}

	@Override
	public LuaValue call() {
		library = tableOf();

		library.set("_object", new LuaUserdata(packet));
		library.set("_class", LuaValue.valueOf(
				packet.getClass().getSimpleName()));

		library.set("clone", new Clone());
		library.set("tojson", new ToJson());

		library.set("has", new Has());
		library.set("get", new Get());
		library.set("set", new Set());
		library.set("count", new Count());
		library.set("keys", new KeySet());
		library.set("all", new All());
		library.set("remove", new Remove());
		library.set("clear", new Clear());

		library.set("tpdu", new Tpdu());
		library.set("head", new Head());
		library.set("dial_ani", new DialAni());
		library.set("dial_dni", new DialDni());

		return library;
	}

	/**
	 * 克隆一个报文，新报文和原报文内容相同
	 */
	class Clone extends ZeroArgFunction
	{
		@Override
		public LuaValue call() {
			Packet clone = packet.clone();
			if (clone == null) {
				return LuaValue.NIL;
			}
			return (new LuaPacket(clone)).call();
		}
	}

	/**
	 * 得到 json 格式的字符串
	 */
	class ToJson extends ZeroArgFunction
	{
		@Override
		public LuaValue call() {
			JsonObject json = packet.toJson();
			return LuaValue.valueOf(json.toString());
		}
	}

	/**
	 * 判断字段是否存在
	 */
	class Has extends OneArgFunction
	{
		@Override
		public LuaValue call(LuaValue arg) {
			return LuaValue.valueOf(packet.has(arg.tojstring()));
		}
	}

	/**
	 * 取报文字段值
	 */
	class Get extends OneArgFunction
	{
		@Override
		public LuaValue call(LuaValue arg) {
			String value = packet.get(arg.tojstring());
			if (value == null) {
				return LuaValue.NIL;
			}
			return LuaValue.valueOf(value);
		}
	}

	/**
	 * 设置报文字段值, 不建议使用此接口
	 */
	class Set extends TwoArgFunction
	{
		@Override
		public LuaValue call(LuaValue arg1, LuaValue arg2) {
			String _name = arg1.tojstring();
			String value = arg2.tojstring();
			return LuaValue.valueOf(packet.set(_name, value));
		}
	}

	/**
	 * 获取报文字段数量
	 */
	class Count extends ZeroArgFunction
	{
		@Override
		public LuaValue call() {
			return LuaValue.valueOf(packet.count());
		}
	}

	/**
	 * 获取报文字段名称集合
	 */
	class KeySet extends ZeroArgFunction
	{
		@Override
		public LuaValue call() {
			LuaValue list = LuaValue.tableOf();
			List<String> keyset = packet.keySet();
			for (int i = 0; i < keyset.size(); i++) {
				list.set(i + 1, keyset.get(i));
			}
			return list;
		}
	}

	/**
	 * 获取所有报文字段
	 */
	class All extends ZeroArgFunction
	{
		@Override
		public LuaValue call() {
			List<String> keyset = packet.keySet();
			LuaValue table = LuaValue.tableOf();
			for (String key : keyset) {
				table.set(key, packet.get(key));
			}
			return table;
		}
	}

	/**
	 * 删除指定的字段，返回被删除字段的值
	 */
	class Remove extends OneArgFunction
	{
		@Override
		public LuaValue call(LuaValue arg) {
			String _name = arg.tojstring();
			String value = packet.get(_name);
			packet.remove(_name);
			if (value == null) {
				return LuaValue.NIL;
			}
			return LuaValue.valueOf(value);
		}
	}

	/**
	 * 清空报文，删除所有的字段
	 */
	class Clear extends ZeroArgFunction
	{
		@Override
		public LuaValue call() {
			packet.clear();
			return LuaValue.valueOf(true);
		}
	}

	/**
	 * 获取或设置 TPDU
	 */
	class Tpdu extends OneArgFunction
	{
		@Override
		public LuaValue call(LuaValue arg) {
			if (arg.isnil()) {
				String v = packet.getTpdu();
				return (v == null) ? LuaValue.NIL : LuaValue.valueOf(v);
			}
			if (packet.setTpdu(arg.tojstring())) {
				return LuaValue.valueOf(packet.getTpdu());
			}
			return LuaValue.NIL;
		}
	}

	/**
	 * 获取或设置报文头
	 */
	class Head extends OneArgFunction
	{
		@Override
		public LuaValue call(LuaValue arg) {
			if (arg.isnil()) {
				String v = packet.getHead();
				return (v == null) ? LuaValue.NIL : LuaValue.valueOf(v);
			}
			if (packet.setHead(arg.tojstring())) {
				return LuaValue.valueOf(packet.getHead());
			}
			return LuaValue.NIL;
		}
	}

	/**
	 * 设置/获取 拨号主叫号码
	 */
	class DialAni extends OneArgFunction
	{
		@Override
		public LuaValue call(LuaValue arg) {
			if (arg.isnil()) {
				String v = packet.getDialANI();
				return (v == null) ? LuaValue.NIL : LuaValue.valueOf(v);
			}
			if (packet.setDialANI(arg.tojstring())) {
				return LuaValue.valueOf(packet.getDialANI());
			}
			return LuaValue.NIL;
		}
	}

	/**
	 * 设置/获取 拨号被叫号码
	 */
	class DialDni extends OneArgFunction
	{
		@Override
		public LuaValue call(LuaValue arg) {
			if (arg.isnil()) {
				String v = packet.getDialDNI();
				return (v == null) ? LuaValue.NIL : LuaValue.valueOf(v);
			}
			if (packet.setDialDNI(arg.tojstring())) {
				return LuaValue.valueOf(packet.getDialDNI());
			}
			return LuaValue.NIL;
		}
	}

}
